
const mapTag = "[object Map]";
const setTag = "[object Set]";
const arrayTag = "[object Array]";
const objectTag = "[object Object]";
const argsTag = "[object Arguments]";

const boolTag = "[object Boolean]";
const dateTag = "[object Date]";
const numberTag = "[object Number]";
const stringTag = "[object String]";
const symbolTag = "[object Symbol]";
const errorTag = "[object Error]";
const regexpTag = "[object RegExp]";
const funcTag = "[object Function]";

const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];


function forEach(array, iteratee) {
	let index = -1;
	const length = array.length;
	while (++index < length) {
		iteratee(array[index], index);
	}
	return array;
}

function isObject(target) {
	const type = typeof target;
	return target !== null && (type === "object" || type === "function");
}

function getType(target) {
	return Object.prototype.toString.call(target);
}

function getInit(target) {
	const Ctor = target.constructor;
	return new Ctor();
}

function cloneSymbol(targe) {
	return Object(Symbol.prototype.valueOf.call(targe));
}

function cloneReg(targe) {
	const reFlags = /\w*$/;
	const result = new targe.constructor(targe.source, reFlags.exec(targe));
	result.lastIndex = targe.lastIndex;
	return result;
}

function cloneFunction(func) {
	const bodyReg = new RegExp("(?<={)(.|\n)+(?=})","m");
	const paramReg = new RegExp("(?<=\\().+(?=\\)\\s+{)");
	const funcString = func.toString();
	if (func.prototype) {
		const param = paramReg.exec(funcString);
		const body = bodyReg.exec(funcString);
		if (body) {
			if (param) {
				const paramArr = param[0].split(",");
				return new Function(...paramArr, body[0]);
			} else {
				return new Function(body[0]);
			}
		} else {
			return null;
		}
	} else {
		return eval(funcString);
	}
}

function cloneOtherType(targe, type) {
	const Ctor = targe.constructor;
	switch (type) {
	case boolTag:
	case numberTag:
	case stringTag:
	case errorTag:
	case dateTag:
		return new Ctor(targe);
	case regexpTag:
		return cloneReg(targe);
	case symbolTag:
		return cloneSymbol(targe);
	case funcTag:
		return cloneFunction(targe);
	default:
		return null;
	}
}

function clone(target, map = new WeakMap()) {

	// 克隆原始类型
	if (!isObject(target)) {
		return target;
	}

	// 初始化
	const type = getType(target);
	let cloneTarget;
	if (deepTag.includes(type)) {
		cloneTarget = getInit(target, type);
	} else {
		return cloneOtherType(target, type);
	}

	// 防止循环引用
	if (map.get(target)) {
		return map.get(target);
	}
	map.set(target, cloneTarget);

	// 克隆set
	if (type === setTag) {
		target.forEach(value => {
			cloneTarget.add(clone(value, map));
		});
		return cloneTarget;
	}

	// 克隆map
	if (type === mapTag) {
		target.forEach((value, key) => {
			cloneTarget.set(key, clone(value, map));
		});
		return cloneTarget;
	}

	// 克隆对象和数组
	const keys = type === arrayTag ? undefined : Object.keys(target);
	forEach(keys || target, (value, key) => {
		if (keys) {
			key = value;
		}
		cloneTarget[key] = clone(target[key], map);
	});

	return cloneTarget;
}

const formatRichText = (html)=> { // 控制小程序中图片大小
	let newContent= html.replace(/<img[^>]*>/gi,function(match,capture){
		match = match.replace(/style="[^"]+"/gi, "").replace(/style='[^']+'/gi, "");
		match = match.replace(/width="[^"]+"/gi, "").replace(/width='[^']+'/gi, "");
		match = match.replace(/height="[^"]+"/gi, "").replace(/height='[^']+'/gi, "");
		return match;
	});
	newContent = newContent.replace(/style="[^"]+"/gi,function(match,capture){
		match = match.replace(/width:[^;]+;/gi, "max-width:100%;").replace(/width:[^;]+;/gi, "max-width:100%;");
		return match;
	});
	newContent = newContent.replace(/<br[^>]*\/>/gi, "");
	newContent = newContent.replace(/<img/gi, "<img style=\"max-width:100%;height:auto;display:inline-block;margin:10rpx auto;\"");
	return newContent;
};

const href = (url,param = {})=>{
	let array = [];
	for(let i in param){
		array.push(`${i}=${param[i]}`);
	}
	if(array.length!==0){
		url = url+"?"+array.join("&");
	}
	uni.navigateTo({
		url:"/pages/"+url
	});
};
const getWeixinCode = () =>{
	return new Promise((resolve, reject) => {
		// #ifdef MP-WEIXIN
		uni.login({
			provider: "weixin",
			success(res) {
				resolve(res.code);
			},
			fail(err) {
				reject(new Error("微信登录失败"));
			}
		});
		// #endif
		// #ifdef APP-PLUS
		weixinAuthService.authorize(function(res) {
			resolve(res.code);
		}, function(err) {
			console.log(err);
			reject(new Error("微信登录失败"));
		});
		// #endif
	});
};
const getStatusbar = ()=>{
	return new Promise(((resolve, reject) => {
		uni.getSystemInfo({
			success: res => {
				// model中包含着设备信息
				resolve (res.statusBarHeight*2);
			},
			fail:e=>reject(e)
		});
	}));

};
function log(data,color="#d00"){
	try {
		data = JSON.stringify(data);
	}
	catch(e){

	}
	console.log("%c"+data,"color:"+color);
}

export { clone ,formatRichText,href,getWeixinCode,getStatusbar,log};